/******
 *
 *    EditArea
 *    Developped by Christophe Dolivet
 *    Released under LGPL, Apache and BSD licenses (use the one you want)
 *
 ******/

function EditArea()
{
	var t = this;
	t.error = false;	// to know if load is interrrupt

	t.inlinePopup = [
		{popup_id: "area_search_replace", icon_id: "search"},
		{popup_id: "edit_area_help", icon_id: "help"}
	];
	t.plugins = {};

	t.line_number = 0;

	parent.editAreaLoader.set_browser_infos(t); 	// navigator identification
	// fix IE8 detection as we run in IE7 emulate mode through X-UA <meta> tag
	if (t.isIE >= 8) {
		t.isIE = 7;
	}

	t.last_selection = {};
	t.last_text_to_highlight = "";
	t.last_hightlighted_text = "";
	t.syntax_list = [];
	t.allready_used_syntax = {};
	t.check_line_selection_timer = 50;	// the timer delay for modification and/or selection change detection

	t.textareaFocused = false;
	t.highlight_selection_line = null;
	t.previous = [];
	t.next = [];
	t.last_undo = "";
	t.files = {};
	t.filesIdAssoc = {};
	t.curr_file = '';
	//t.loaded= false;
	t.assocBracket = {};
	t.revertAssocBracket = {};
	// bracket selection init
	t.assocBracket["("] = ")";
	t.assocBracket["{"] = "}";
	t.assocBracket["["] = "]";
	for (var index in t.assocBracket) {
		t.revertAssocBracket[t.assocBracket[index]] = index;
	}
	t.is_editable = true;

	/*t.textarea="";

	 t.state="declare";
	 t.code = []; // store highlight syntax for languagues*/
	// font datas
	t.lineHeight = 16;
	/*t.default_font_family= "monospace";
	 t.default_font_size= 10;*/
	t.tab_nb_char = 8;	//nb of white spaces corresponding to a tabulation
	if (t.isOpera) {
		t.tab_nb_char = 6;
	}

	t.is_tabbing = false;

	t.fullscreen = {'isFull': false};

	t.isResizing = false;	// resize var

	// init with settings and ID (area_id is a global var defined by editAreaLoader on iframe creation
	t.id = area_id;
	t.settings = editAreas[t.id]["settings"];

	if (("" + t.settings['replace_tab_by_spaces']).match(/^[0-9]+$/)) {
		t.tab_nb_char = t.settings['replace_tab_by_spaces'];
		t.tabulation = "";
		for (var i = 0; i < t.tab_nb_char; i++) {
			t.tabulation += " ";
		}
	} else {
		t.tabulation = "\t";
	}

	// retrieve the init parameter for syntax
	if (t.settings["syntax_selection_allow"] && t.settings["syntax_selection_allow"].length > 0) {
		t.syntax_list = t.settings["syntax_selection_allow"].replace(/ /g, "").split(",");
	}

	if (t.settings['syntax']) {
		t.allready_used_syntax[t.settings['syntax']] = true;
	}

};
EditArea.prototype.init = function()
{
	var t = this, a, s = t.settings;
	t.textarea = _$("textarea");
	t.container = _$("container");
	t.result = _$("result");
	t.content_highlight = _$("content_highlight");
	t.selection_field = _$("selection_field");
	t.selection_field_text = _$("selection_field_text");
	t.processing_screen = _$("processing");
	t.editor_area = _$("editor");
	t.tab_browsing_area = _$("tab_browsing_area");
	t.test_font_size = _$("test_font_size");
	a = t.textarea;

	if (!s['is_editable']) {
		t.set_editable(false);
	}

	t.set_show_line_colors(s['show_line_colors']);

	if (syntax_selec = _$("syntax_selection")) {
		// set up syntax selection lsit in the toolbar
		for (var i = 0; i < t.syntax_list.length; i++) {
			var syntax = t.syntax_list[i];
			var option = document.createElement("option");
			option.value = syntax;
			if (syntax == s['syntax']) {
				option.selected = "selected";
			}
			option.innerHTML = t.get_translation("syntax_" + syntax, "word");
			syntax_selec.appendChild(option);
		}
	}

	// add plugins buttons in the toolbar
	spans = parent.getChildren(_$("toolbar_1"), "span", "", "", "all", -1);

	for (var i = 0; i < spans.length; i++) {

		id = spans[i].id.replace(/tmp_tool_(.*)/, "$1");
		if (id != spans[i].id) {
			for (var j in t.plugins) {
				if (typeof(t.plugins[j].get_control_html) == "function") {
					html = t.plugins[j].get_control_html(id);
					if (html != false) {
						html = t.get_translation(html, "template");
						var new_span = document.createElement("span");
						new_span.innerHTML = html;
						var father = spans[i].parentNode;
						spans[i].parentNode.replaceChild(new_span, spans[i]);
						break; // exit the for loop
					}
				}
			}
		}
	}

	// init datas
	//a.value	= 'a';//editAreas[t.id]["textarea"].value;

	if (s["debug"]) {
		t.debug = parent.document.getElementById("edit_area_debug_" + t.id);
	}
	// init size
	//this.update_size();

	if (_$("redo") != null) {
		t.switchClassSticky(_$("redo"), 'editAreaButtonDisabled', true);
	}

	// insert css rules for highlight mode
	if (typeof(parent.editAreaLoader.syntax[s["syntax"]]) != "undefined") {
		for (var i in parent.editAreaLoader.syntax) {
			if (typeof(parent.editAreaLoader.syntax[i]["styles"]) != "undefined") {
				t.add_style(parent.editAreaLoader.syntax[i]["styles"]);
			}
		}
	}

	// init key events
	if (t.isOpera) {
		_$("editor").onkeypress = keyDown;
	}
	else {
		_$("editor").onkeydown = keyDown;
	}

	for (var i = 0; i < t.inlinePopup.length; i++) {
		if (t.isOpera) {
			_$(t.inlinePopup[i]["popup_id"]).onkeypress = keyDown;
		}
		else {
			_$(t.inlinePopup[i]["popup_id"]).onkeydown = keyDown;
		}
	}

	if (s["allow_resize"] == "both" || s["allow_resize"] == "x" || s["allow_resize"] == "y") {
		t.allow_resize(true);
	}

	parent.editAreaLoader.toggle(t.id, "on");
	//a.focus();
	// line selection init
	t.change_smooth_selection_mode(editArea.smooth_selection);
	// highlight
	t.execCommand("change_highlight", s["start_highlight"]);

	// get font size datas
	t.set_font(editArea.settings["font_family"], editArea.settings["font_size"]);

	// set unselectable text
	children = parent.getChildren(document.body, "", "selec", "none", "all", -1);
	for (var i = 0; i < children.length; i++) {
		if (t.isIE) {
			children[i].unselectable = true;
		} // IE
		else {
			children[i].onmousedown = function() {return false};
		}
		/*	children[i].style.MozUserSelect = "none"; // Moz
		 children[i].style.KhtmlUserSelect = "none";  // Konqueror/Safari*/
	}

	a.spellcheck = s["gecko_spellcheck"];

	/** Browser specific style fixes **/

	// fix rendering bug for highlighted lines beginning with no tabs
	if (t.isFirefox >= '3') {
		t.content_highlight.style.paddingLeft = "1px";
		t.selection_field.style.paddingLeft = "1px";
		t.selection_field_text.style.paddingLeft = "1px";
	}

	if (t.isIE && t.isIE < 8) {
		a.style.marginTop = "-1px";
	}
	/*
	 if(t.isOpera){
	 t.editor_area.style.position= "absolute";
	 }*/

	if (t.isSafari) {
		t.editor_area.style.position = "absolute";
		a.style.marginLeft = "-3px";
		if (t.isSafari < 3.2) // Safari 3.0 (3.1?)
		{
			a.style.marginTop = "1px";
		}
	}

	// si le textarea n'est pas grand, un click sous le textarea doit provoquer un focus sur le textarea
	parent.editAreaLoader.add_event(t.result, "click", function(e)
	{
		if ((e.target || e.srcElement) == editArea.result) {
			editArea.area_select(editArea.textarea.value.length, 0);
		}
	});

	if (s['is_multi_files'] != false) {
		t.open_file({'id': t.curr_file, 'text': ''});
	}

	t.set_word_wrap(s['word_wrap']);

	setTimeout("editArea.focus();editArea.manage_size();editArea.execCommand('EA_load');", 10);
	//start checkup routine
	t.check_undo();
	t.check_line_selection(true);
	t.scroll_to_view();

	for (var i in t.plugins) {
		if (typeof(t.plugins[i].onload) == "function") {
			t.plugins[i].onload();
		}
	}
	if (s['fullscreen'] == true) {
		t.toggle_full_screen(true);
	}

	parent.editAreaLoader.add_event(window, "resize", editArea.update_size);
	parent.editAreaLoader.add_event(parent.window, "resize", editArea.update_size);
	parent.editAreaLoader.add_event(top.window, "resize", editArea.update_size);
	parent.editAreaLoader.add_event(window, "unload", function()
	{
		// in case where editAreaLoader have been already cleaned
		if (parent.editAreaLoader) {
			parent.editAreaLoader.remove_event(parent.window, "resize", editArea.update_size);
			parent.editAreaLoader.remove_event(top.window, "resize", editArea.update_size);
		}
		if (editAreas[editArea.id] && editAreas[editArea.id]["displayed"]) {
			editArea.execCommand("EA_unload");
		}
	});

	/*date= new Date();
	 alert(date.getTime()- parent.editAreaLoader.start_time);*/
};

//called by the toggle_on
EditArea.prototype.update_size = function()
{
	var d = document, pd = parent.document, height, width, popup, maxLeft, maxTop;

	if (typeof editAreas != 'undefined' && editAreas[editArea.id] && editAreas[editArea.id]["displayed"] == true) {
		if (editArea.fullscreen['isFull']) {
			pd.getElementById("frame_" + editArea.id).style.width = pd.getElementsByTagName("html")[0].clientWidth + "px";
			pd.getElementById("frame_" + editArea.id).style.height = pd.getElementsByTagName("html")[0].clientHeight + "px";
		}

		if (editArea.tab_browsing_area.style.display == 'block' && ( !editArea.isIE || editArea.isIE >= 8 )) {
			editArea.tab_browsing_area.style.height = "0px";
			editArea.tab_browsing_area.style.height = (editArea.result.offsetTop - editArea.tab_browsing_area.offsetTop - 1) + "px";
		}

		height = d.body.offsetHeight - editArea.get_all_toolbar_height() - 4;
		editArea.result.style.height = height + "px";

		width = d.body.offsetWidth - 2;
		editArea.result.style.width = width + "px";
		//alert("result h: "+ height+" w: "+width+"\ntoolbar h: "+this.get_all_toolbar_height()+"\nbody_h: "+document.body.offsetHeight);

		// check that the popups don't get out of the screen
		for (i = 0; i < editArea.inlinePopup.length; i++) {
			popup = _$(editArea.inlinePopup[i]["popup_id"]);
			maxLeft = d.body.offsetWidth - popup.offsetWidth;
			maxTop = d.body.offsetHeight - popup.offsetHeight;
			if (popup.offsetTop > maxTop) {
				popup.style.top = maxTop + "px";
			}
			if (popup.offsetLeft > maxLeft) {
				popup.style.left = maxLeft + "px";
			}
		}

		editArea.manage_size(true);
		editArea.fixLinesHeight(editArea.textarea.value, 0, -1);
	}
};

EditArea.prototype.manage_size = function(onlyOneTime)
{
	if (!editAreas[this.id]) {
		return false;
	}

	if (editAreas[this.id]["displayed"] == true && this.textareaFocused) {
		var area_height, resized = false;

		//1) Manage display width
		//1.1) Calc the new width to use for display
		if (!this.settings['word_wrap']) {
			var area_width = this.textarea.scrollWidth;
			area_height = this.textarea.scrollHeight;
			// bug on old opera versions
			if (this.isOpera && this.isOpera < 9.6) {
				area_width = 10000;
			}
			//1.2) the width is not the same, we must resize elements
			if (this.textarea.previous_scrollWidth != area_width) {
				this.container.style.width = area_width + "px";
				this.textarea.style.width = area_width + "px";
				this.content_highlight.style.width = area_width + "px";
				this.textarea.previous_scrollWidth = area_width;
				resized = true;
			}
		}
		// manage wrap width
		if (this.settings['word_wrap']) {
			newW = this.textarea.offsetWidth;
			if (this.isFirefox || this.isIE) {
				newW -= 2;
			}
			if (this.isSafari) {
				newW -= 6;
			}
			this.content_highlight.style.width = this.selection_field_text.style.width = this.selection_field.style.width = this.test_font_size.style.width = newW + "px";
		}

		//2) Manage display height
		//2.1) Calc the new height to use for display
		if (this.isOpera || this.isFirefox || this.isSafari) {
			area_height = this.getLinePosTop(this.last_selection["nb_line"] + 1);
		} else {
			area_height = this.textarea.scrollHeight;
		}
		//2.2) the width is not the same, we must resize elements
		if (this.textarea.previous_scrollHeight != area_height) {
			this.container.style.height = (area_height + 2) + "px";
			this.textarea.style.height = area_height + "px";
			this.content_highlight.style.height = area_height + "px";
			this.textarea.previous_scrollHeight = area_height;
			resized = true;
		}

		//3) if there is new lines, we add new line numbers in the line numeration area
		if (this.last_selection["nb_line"] >= this.line_number) {
			var newLines = '', destDiv = _$("line_number"), start = this.line_number, end = this.last_selection["nb_line"] + 100;
			for (i = start + 1; i < end; i++) {
				newLines += '<div id="line_' + i + '">' + i + "</div>";
				this.line_number++;
			}
			destDiv.innerHTML = destDiv.innerHTML + newLines;

			this.fixLinesHeight(this.textarea.value, start, -1);
		}

		//4) be sure the text is well displayed
		this.textarea.scrollTop = "0px";
		this.textarea.scrollLeft = "0px";
		if (resized == true) {
			this.scroll_to_view();
		}
	}

	if (!onlyOneTime) {
		setTimeout("editArea.manage_size();", 100);
	}
};

EditArea.prototype.execCommand = function(cmd, param)
{

	for (var i in this.plugins) {
		if (typeof(this.plugins[i].execCommand) == "function") {
			if (!this.plugins[i].execCommand(cmd, param)) {
				return;
			}
		}
	}
	switch (cmd) {
		case "save":
			if (this.settings["save_callback"].length > 0) {
				eval("parent." + this.settings["save_callback"] + "('" + this.id + "', editArea.textarea.value);");
			}
			break;
		case "load":
			if (this.settings["load_callback"].length > 0) {
				eval("parent." + this.settings["load_callback"] + "('" + this.id + "');");
			}
			break;
		case "onchange":
			if (this.settings["change_callback"].length > 0) {
				eval("parent." + this.settings["change_callback"] + "('" + this.id + "');");
			}
			break;
		case "EA_load":
			if (this.settings["EA_load_callback"].length > 0) {
				eval("parent." + this.settings["EA_load_callback"] + "('" + this.id + "');");
			}
			break;
		case "EA_unload":
			if (this.settings["EA_unload_callback"].length > 0) {
				eval("parent." + this.settings["EA_unload_callback"] + "('" + this.id + "');");
			}
			break;
		case "toggle_on":
			if (this.settings["EA_toggle_on_callback"].length > 0) {
				eval("parent." + this.settings["EA_toggle_on_callback"] + "('" + this.id + "');");
			}
			break;
		case "toggle_off":
			if (this.settings["EA_toggle_off_callback"].length > 0) {
				eval("parent." + this.settings["EA_toggle_off_callback"] + "('" + this.id + "');");
			}
			break;
		case "re_sync":
			if (!this.do_highlight) {
				break;
			}
		case "file_switch_on":
			if (this.settings["EA_file_switch_on_callback"].length > 0) {
				eval("parent." + this.settings["EA_file_switch_on_callback"] + "(param);");
			}
			break;
		case "file_switch_off":
			if (this.settings["EA_file_switch_off_callback"].length > 0) {
				eval("parent." + this.settings["EA_file_switch_off_callback"] + "(param);");
			}
			break;
		case "file_close":
			if (this.settings["EA_file_close_callback"].length > 0) {
				return eval("parent." + this.settings["EA_file_close_callback"] + "(param);");
			}
			break;

		default:
			if (typeof(eval("editArea." + cmd)) == "function") {
				if (this.settings["debug"]) {
					eval("editArea." + cmd + "(param);");
				}
				else {
					try {
						eval("editArea." + cmd + "(param);");
					} catch (e) {
					}
				}
				;
			}
	}
};

EditArea.prototype.get_translation = function(word, mode)
{
	if (mode == "template") {
		return parent.editAreaLoader.translate(word, this.settings["language"], mode);
	}
	else {
		return parent.editAreaLoader.get_word_translation(word, this.settings["language"]);
	}
};

EditArea.prototype.add_plugin = function(plug_name, plug_obj)
{
	for (var i = 0; i < this.settings["plugins"].length; i++) {
		if (this.settings["plugins"][i] == plug_name) {
			this.plugins[plug_name] = plug_obj;
			plug_obj.baseURL = parent.editAreaLoader.baseURL + "plugins/" + plug_name + "/";
			if (typeof(plug_obj.init) == "function") {
				plug_obj.init();
			}
		}
	}
};

EditArea.prototype.load_css = function(url)
{
	try {
		link = document.createElement("link");
		link.type = "text/css";
		link.rel = "stylesheet";
		link.media = "all";
		link.href = url;
		head = document.getElementsByTagName("head");
		head[0].appendChild(link);
	} catch (e) {
		document.write("<link href='" + url + "' rel='stylesheet' type='text/css' />");
	}
};

EditArea.prototype.load_script = function(url)
{
	try {
		script = document.createElement("script");
		script.type = "text/javascript";
		script.src = url;
		script.charset = "UTF-8";
		head = document.getElementsByTagName("head");
		head[0].appendChild(script);
	} catch (e) {
		document.write("<script type='text/javascript' src='" + url + "' charset=\"UTF-8\"><" + "/script>");
	}
};

// add plugin translation to language translation array
EditArea.prototype.add_lang = function(language, values)
{
	if (!parent.editAreaLoader.lang[language]) {
		parent.editAreaLoader.lang[language] = {};
	}
	for (var i in values) {
		parent.editAreaLoader.lang[language][i] = values[i];
	}
};

// short cut for document.getElementById()
function _$(id) {return document.getElementById(id);};

var editArea = new EditArea();
parent.editAreaLoader.add_event(window, "load", init);

function init()
{
	setTimeout("editArea.init();  ", 10);
};
